﻿using System;
using System.ServiceModel;
using System.Collections.Generic;

namespace BOOKCACHINGServiceRole
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IBookCachingService" in both code and config file together.
    [ServiceContract]
    [ServiceKnownType(typeof(List<string>))]
    [ServiceKnownType(typeof(Book))]
    [ServiceKnownType(typeof(BookState))]
    [ServiceKnownType(typeof(Event))]
    [ServiceKnownType(typeof(List<Book>))]
    [ServiceKnownType(typeof(List<Places>))]
    [ServiceKnownType(typeof(User))]

    public interface IBookCachingService
    {
        /// <summary>
        /// Add a new user
        /// </summary>
        /// <param name="fullName">Full name</param>
        /// <param name="userName">Username</param>
        /// <param name="passwordHash">SHA1 hash of password</param> 
        
        [OperationContract]
        void AddUser(string fullName, string userName, string passwordHash);
        /// <summary>
        /// Authenticates user with username name a password hash
        /// </summary>
        /// <param name="userName">Username - plain text</param>
        /// <param name="password">Password - SHA1 hash</param>
        /// <returns></returns>
        [OperationContract]
        User LoginUser(string userName, string passwordHash);

        /// <summary>
        /// Gets user by id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [OperationContract]
        User GetUserById(int id);

        //[OperationContract]
        //List<string> GetBookNameByID(int id);
        ///// <summary>
        /// Gets Book by ID
        /// </summary>
        /// <param name="id">Book ID</param>
        /// <returns>Book or null of ID not found</returns>
        [OperationContract]
        Book GetBookByID(int id);

        /// <summary>
        /// Selects books in a square around coordinates of a defined size
        /// </summary>
        /// <param name="lat">Latitude</param>
        /// <param name="lon">Longitude</param>
        /// <param name="distance">Distance in meteres</param>
        /// <param name="alreadyLoaded">List of b ids, that are already loaded in device</param>
        /// <returns>List of books in selected square</returns>
        [OperationContract]
        List<Book> GetBooksByDistance(double lat, double lon, double distance, List<Int32> alreadyLoaded = null);

        /// <summary>
        /// Selects places in defined square
        /// </summary>
        /// <param name="latUL">Latitude upper left corner</param>
        /// <param name="lonUL">Longitude upper left corner</param>
        /// <param name="latUL">Latitude bottom right corner</param>
        /// <param name="lonUL">Longitude bottom right corner</param>
        /// <param name="alreadyLoaded">List of places ids, that are already loaded in device</param>
        /// <returns>List of places in selected square</returns>
        [OperationContract]
        List<Book> GetBooksByArea(double latUL, double lonUL, double latBR, double lonBR, List<Int32> alreadyLoaded = null);
        
        /// <summary>
        /// Gets list of all books currently borrowed by specified user
        /// </summary>
        /// <param name="userId">ID of user</param>
        /// <returns>List of currently selected books</returns>
        [OperationContract]
        List<Book> GetBorrowedBooks(int userId);

        /// <summary>
        /// Gets list of all books owned by the user
        /// </summary>
        /// <param name="userId">ID of user</param>
        /// <returns>List of books owned by the user</returns>
        [OperationContract]
        List<Book> GetUserBooks(int userId);


        /// <summary>
        /// Gets list of all books user found
        /// </summary>
        /// <param name="userId">ID of user</param>
        /// <returns>List of all books user found</returns>
        [OperationContract]
        List<Book> GetFoundBooks(int userId);

        /// <summary>
        /// Creates event of returning book and sets bookstate, automaticky inserts user id of the user who borrowed the book, sets book new location
        /// </summary>
        /// <param name="bookId">ID of book</param>
        /// <param name="placeId">ID of place - null if book is not returned to known place</param>
        /// <param name="lat">Latitude, null of placeID used</param>
        /// <param name="lon">Longitude, null of placeID used</param>
        /// <param name="description">Optional event description, use null if not specified</param>
        /// <returns>Any error that occured, null if everything OK</returns>
        [OperationContract]
        string ReturnBook(int bookId, int? placeId, float? lat, float? lon, string description);

        /// <summary>
        /// Creates a borrow event of the book, sets user who borrowed it and bookstate, resets books lat nad lon
        /// </summary>
        /// <param name="bookId">Book ID</param>
        /// <param name="userId">User ID</param>
        /// <returns>Any error that occured, null if everything OK</returns>
        [OperationContract]
        string BorrowBook(int bookId, int userId);


        /// <summary>
        /// Creates a find event of the book
        /// </summary>
        /// <param name="bookId">Book ID</param>
        /// <param name="userId">User ID</param>
        /// <returns>Any error that occured, null if everything OK</returns>
        [OperationContract]
        string FindBook(int bookId, int userId);

        /// <summary>
        /// Gets place by ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [OperationContract]
        Places GetPlaceById(int id);
        

        /// <summary>
        /// Selects places in defined distance
        /// </summary>
        /// <param name="lat">Latitude</param>
        /// <param name="lon">Longitude</param>
        /// <param name="distance">Distance from place in meters</param>
        /// <param name="alreadyLoaded">List of places ids, that are already loaded in device</param>
        /// <returns>List of places in selected distance</returns>
        [OperationContract]
        List<Places> GetPlacesByDistance(double lat, double lon, double distance, List<Int32> alreadyLoaded = null);

        /// <summary>
        /// Selects places in defined square
        /// </summary>
        /// <param name="latUL">Latitude upper left corner</param>
        /// <param name="lonUL">Longitude upper left corner</param>
        /// <param name="latUL">Latitude bottom right corner</param>
        /// <param name="lonUL">Longitude bottom right corner</param>
        /// <param name="alreadyLoaded">List of places ids, that are already loaded in device</param>
        /// <returns>List of places in selected square</returns>
        [OperationContract]
        List<Places> GetPlacesByArea(double latUL, double lonUL, double latBR, double lonBR, List<Int32> alreadyLoaded = null);
        [OperationContract]
        string Test();
    }
}
